#include <iostream>
#include "XApplication.hpp"
#include "XSender.hpp"
#include "XReciver.hpp"
#include "threadRALL.hpp"
#include"xsignal/xtimer.hpp"

/*
	建议gcc8.1，也可选择其它版本，但需支持c++17。
	本示例代码主要验证使用xsignal类实现类似Qt信号槽机制。
	代码结构规整，具体实现见源代码，本简要主要说明模块的使用
	1.xsignal文件夹下为信号槽的实现源码
	2.XApplication是一个可实现消息注册回调的类，
	用户可指定消息类型，如“int”、“string”,然后使用registerCallback
	进行注册，当调用XApplication::exec()时，便进入主线程消息循环，
	程序即开始等待用户的输入，若输入的消息与规定的消息类型一致，
	且该消息已注册，就跳转执行回调函数，当用户按下组合键“ctrl+z”时，
	主线程消息循环结束。这对于基于控制台的代码测试非常方便，
	用户也可采取常规方式验证xsignal。
	2.xtimer定时器类，定时器可定是发射触发信号，需要只需要与该信号
	绑定，即可执行定时操作。
*/

//子线程，内部开启线程消息循环，读取消息队列

void thrdMessageDeal(XSender* pSender){
	struct customReciver : public SIG::sigReciver
	{
		void slot(){std::cout << "customReciver::slot()" << std::endl;}
		~customReciver(){
			std::cout<<"customReciver dtor!"<<std::endl;
		}
	};

	//
	//[1--创建线程消息队列]
	SIG_THREAD_INIT();

	//创建定时器
	xtimer timer;
	customReciver * recvier = new customReciver;

	//绑定定时器超时槽函数
	SIG::connect(&timer,&xtimer::sinTimeout,[](){
		std::cout<<"thrdID:"<<std::this_thread::get_id()<<" xtimer trigger"<<std::endl;
	},SIG::connectType::queueConnection);

	//模拟接收者在任务队列未处理完后就已经析构的情况
	static int count =0;
	SIG::connect(&timer,&xtimer::sinTimeout,[recvier](){
		if(count ==6)	return;
		if(count<5)
			std::this_thread::sleep_for(1s);
		if(count==5){
			std::this_thread::sleep_for(5s);
			SIG::sigReciver::deleteLater(recvier);
		}
		count++;
	},SIG::connectType::queueConnection);

	SIG::connect(&timer,&xtimer::sinTimeout,recvier,&customReciver::slot,SIG::connectType::queueConnection);

	//启动定时器
	//timer.start(1000);	//可手动关闭，若未关闭，定时器对象析构时自动关闭

	static bool runflag = true;		//循环控制

	// 连接信号槽
	pSender->AttachsignalSlot();

	//用户需要负责线程的关闭
	SIG::connect(pSender,&XSender::signalStop,[](){runflag = false;},SIG::connectType::queueConnection);

	//单次触发
	SIG::SingleSlot([](int t){std::cout<<std::this_thread::get_id()<<" SIG::SingleSlot "<<t<<std::endl;},10);

	//
	//[2--消息循环]

	SIG_THREAD_EXEC(runflag);

	//
	//[3--销毁线程消息队列]
	SIG_THREAD_CLEAR();
	std::cout<<__FUNCTION__<<" leave"<<std::endl;
}

int main(int argc,char**argv)
{	
	//信号接收者
	XReciver* pReciver = new XReciver();

	//信号发送者
	XSender sender(pReciver);

	//创建子线程
	threadRALL t(std::thread(thrdMessageDeal,&sender),threadRALL::DtorAction::join);

	XApplication<int> a(argc,argv);
	a.registerCallback(1, [&sender](){sender.testRepeatConnect();});										//信号槽的重复绑定
	a.registerCallback(2, [&sender](){sender.testQueBlockConnect();});									  //测试阻塞队列连接
	a.registerCallback(3, [&sender](){sender.testDirecrConnect();});									    //测试直接连接
	a.registerCallback(4, [&sender](){sender.testEmitLambdaSignal();});									//槽绑定Lambda函数对象

	a.registerCallback(5, [&sender](){sender.tesEmitGlobalFunSignal();});								//绑定全局函数
	a.registerCallback(6, [&sender](){sender.testSignalEmitDisconnectGlobalFun();});			//解绑信号槽后发射信号

	a.registerCallback(7, [&sender](){sender.testEmitSigalTest3();});							   			 //未解绑之前发射信号
	a.registerCallback(8, [&sender](){sender.testEmitSignalDisConnect();});							   //解绑信号槽后发射信号
	
	a.registerCallback(9, [&sender](){sender.testEmitThrdStopSignal();});								//主线程发射线程终止信号，子线程终止后，观察槽函数执行行为
	a.registerCallback(10, [&pReciver](){delete pReciver;});										  				//接收者析构后，观察槽函数的执行行为
	a.m_content =  "//---------------------------------------\n"
                    "功能列表--list\n"
                    "1    testRepeatConnect\n"
                    "2    testQueBlockConnect\n"
                    "3    testDirecrConnect\n"
                    "4    testEmitLambdaSignal\n"
                    "5    tesEmitGlobalFunSignal\n"
                    "6    testSignalEmitDisconnectGlobalFun\n"
                    "7    testEmitSigalTest3\n"
                    "8    testEmitSignalDisConnect\n"
                    "9    testEmitThrdStopSignal\n"
                    "10  testDeleteReciver\n"
				   "//---------------------------------------\n";
	//ctrl+z结束a.exec
    return a.exec([](std::string str)->int{return std::stoi(str);});
}